/******************************************************************************
NAME:                         RGB2HIS
 
PURPOSE    To process red,green,blue bands to hue,intensity,saturation.
 
ALGORITHM:
   Get red, green, blue from input buffer
   Create the HIS bands
   Write to output buffer
 
ASSUMPTION:
   The input images are read to the input buffer.
 
******************************************************************************/
/* For GRASS one row from each cell map is passed in and each cell in
   each band is processed and written out.   CWU GIS Lab: DBS 8/90*/

#include <grass/gis.h>
#include "globals.h"

void 
rgb2his (CELL *rowbuffer[3], int columns)
{
  int    sample;		/* sample indicator                      */
  double   red;			/* the red band output                   */
  double   green;		/* the green band output                 */
  double   blue;		/* the blue band output                  */
  double   scaler;		/* red value                             */
  double   scaleg;		/* green value                           */
  double   scaleb;		/* blue value                            */
  double   high;		/* maximum red, green, blue              */
  double   low;			/* minimum red, green, blue              */
  double   intens;		/* intensity                             */
  double   sat;			/* saturation                            */
  double   hue=0.0L;		/* hue                                   */
 
  for (sample= 0;sample < columns; sample++)
    {
      scaler = (double) rowbuffer[0][sample];
      scaler /= 255.0;
      scaleg = (double) rowbuffer[1][sample];
      scaleg /= 255.0;
      scaleb = (double) rowbuffer[2][sample];
      scaleb /= 255.0;
 
      high = scaler;
      if (scaleg > high)
	high = scaleg;
      if (scaleb > high)
	high = scaleb;
      low = scaler;
      if (scaleg < low)
	low = scaleg;
      if (scaleb < low)
	low = scaleb;
      /*
	calculate the lightness (intensity)
	*/
      intens = ((high + low) / 2.0);
      /*
	if min = max the achromatic case R=G=B
	*/
      if (high == low)
        {
	  sat = 0.0;
	  /*        hue = -1.0; */
	  hue = 0.0;
	  rowbuffer[0][sample] = (unsigned char) hue;
	  rowbuffer[1][sample] = (unsigned char) (intens*255.);
	  rowbuffer[2][sample] = (unsigned char) (sat*255.);
        }
      /*
	else chromatic case
	*/
      else if (high != low)
        {
	  if (intens <= 0.5)
	    sat = (high-low)/(high+low);
	  else
	    /*
	      sat = (high-low)/(2 - (high-low));
	      */
	    sat = (high-low)/(2 - high - low);
	  red = (high-scaler)/(high-low);
	  green=(high-scaleg)/(high-low);
	  blue =(high-scaleb)/(high-low);
	  /*
	    resulting color between yellow and magenta
	    */
	  if (scaler == high)
	    hue = blue - green;
	  /*
	    resulting color between cyan and yellow
	    */
	  else
	    if (scaleg == high)
	      hue = 2 + red - blue;
	  /*
	    resulting color between magenta and cyan
	    */
	    else
	      if (scaleb == high)
		hue = 4 + green - red;
	  /*
	    convert to degrees
	    */
	  hue *= 60.0;
	  /*
	    make nonnegative
	    */
	  if (hue < 0.0)
	    hue += 360.0;
	  /*
	    set the HIS output values
	    */
	  rowbuffer[0][sample] = (unsigned char)(255.0 * hue / 360.0 + 0.5);
	  rowbuffer[1][sample] = (unsigned char) (intens*255. + 0.5);
	  rowbuffer[2][sample] = (unsigned char) (sat*255. + 0.5);
        }
    }
}
